package gugga.tasks
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import gugga.eventHelpers.EventDescriptor;
	import gugga.eventHelpers.Listener;
	import gugga.tasks.events.TaskEvent;

	[Event(name="start", type="TaskEvent")]
	[Event(name="interrupted", type="TaskEvent")]
	[Event(name="completed", type="TaskEvent")]

	/**
	 * <code>SingleExecutionTask</code> is a wrapper for an <code>ITask</code> that should be 
	 * executed only once. If started for a second time it will immediately dispatch 
	 * <b><i>completed</i></b>-event.
	 */
	public class SingleExecutionTask extends EventDispatcher implements ITask
	{
		private var mIsRunning:Boolean;
	
		private var mActualTask : ITask;
		private var mExecuted : Boolean = false;
		
		public function SingleExecutionTask(aActualTask : ITask) 
		{
			super();
			
			mIsRunning = false;
			
			mActualTask = aActualTask;
			mActualTask.addEventListener(TaskEvent.COMPLETED, onCompleted);
			mActualTask.addEventListener(TaskEvent.START, onStarted);	
		}
		
		public function start() : void 
		{
			if(!mExecuted)
			{
				mIsRunning = true;
				mActualTask.start();
				mExecuted = true;
			}
			else
			{
				//TODO: It was dispatchEventLater in prevoius version
				dispatchEvent(new TaskEvent(TaskEvent.COMPLETED));
			}
		}
		
		public function isRunning() : Boolean 
		{
			return mIsRunning;
		}
		
		public function isImmediatelyInterruptable() : Boolean
		{
			return mActualTask.isImmediatelyInterruptable();
		}
		
		public function interrupt() : void
		{
			Listener.createSingleTimeListener(new EventDescriptor(mActualTask, TaskEvent.INTERRUPTED), onActualTaskInterrupted);
			
			mActualTask.interrupt();
		}
		
		private function onStarted(aEvent : Event) : void
		{
			mExecuted = true;
			
			dispatchEvent(aEvent);
		}
		
		private function onActualTaskInterrupted(ev : Object) : void
		{
			mIsRunning = false;
			dispatchEvent(new TaskEvent(TaskEvent.INTERRUPTED));
		}
		
		private function onCompleted(aEvent : Event) : void
		{
			mIsRunning = false;

			dispatchEvent(aEvent);
		}		
	}
}